//bange_base.cpp
//Copyright (C) 2010-2011 Oscar (.teri) Triano

//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.

//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//GNU General Public License for more details.

//You should have received a copy of the GNU General Public License
//along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <bange_base.hpp>

bange::base *bange::base::GetBaseFromProxy(int index, lua_State *vm){
	bange::baseproxy *baseproxy = static_cast<bange::baseproxy *>(lua_touserdata(vm, index));
	return baseproxy->base;
}

void bange::base::RegisterVM(lua_State *vm){
	luaL_Reg metabaseproxy[] = {
	{"__newindex", bangebaseproxy_newindex},
	{"__index", bangebaseproxy_index},
	{"__tostring", bangebaseproxy_tostring},
	{"__gc", bangebaseproxy_gc},
	{NULL, NULL}};
	luaL_newmetatable(vm, "bange::baseproxy");
	luaL_register(vm, NULL, metabaseproxy);
	lua_pop(vm, 1);
}

void bange::BuildProxy(int refparent, bange::base *base, lua_State *vm){
	bange::baseproxy *baseproxy = static_cast<bange::baseproxy *>(lua_newuserdata(vm, sizeof(bange::baseproxy)));
	baseproxy->refparent = refparent;
	baseproxy->base = base;
	lua_getfield(vm, LUA_REGISTRYINDEX, "bange::baseproxy");
	lua_setmetatable(vm, -2);
}

static int bangebaseproxy_newindex(lua_State *vm){
	//proxy, key, data
	bange::base *base = bange::base::GetBaseFromProxy(1, vm);
	base->NewIndex(vm);
}

static int bangebaseproxy_index(lua_State *vm){
	//proxy, key
	bange::base *base = bange::base::GetBaseFromProxy(1, vm);
	base->Index(vm);
}

static int bangebaseproxy_tostring(lua_State *vm){
	//proxy
	bange::base *base = bange::base::GetBaseFromProxy(1, vm);
	lua_pushstring(vm, base->ToString().c_str());
	return 1;
}

static int bangebaseproxy_gc(lua_State *vm){
	//proxy
	bange::baseproxy *proxy = static_cast<bange::baseproxy *>(lua_touserdata(vm, 1));
	#ifdef BASE_DEBUG
	cout << "Proxy: " << lua_touserdata(vm, 1) << " deleted and freeing: " << proxy << " resource" << \
	" whit base: " << proxy->base << endl;
	#endif
	if (proxy->refparent == LUA_REFNIL){
		proxy->base->CleanVM(vm);
		delete proxy->base;}
	else{
		luaL_unref(vm, LUA_REGISTRYINDEX, proxy->refparent);}
}
